//
//  PJString.h
//  PJlib
//
//  Created by Pang Jun on 12/8/12.
//  Copyright (c) 2012 Pang Jun. All rights reserved.
//

#ifndef __PJlib__PJString__
#define __PJlib__PJString__

#include "pj_memory_configure.h"
//#include <string>

template<class CHARTYPE, int MODETYPE = 0, class ALLOCATOR = MemoryConfigure<CHARTYPE> >
class BaseString
{
private:
	struct ReferenceCounter
	{
		unsigned int Length;
		unsigned int Capacity;
		int  memoryRef;
		bool isPrivate;
		CHARTYPE* CString()
		{
			return reinterpret_cast<CHARTYPE *>(this+1);
		}
		CHARTYPE& operator[](unsigned int nPos)
		{
			return CString()[nPos];
		}
		CHARTYPE* Assign()
		{
			if(isPrivate)
			{
				return DeepCopy();
			}
			else
			{
				++memoryRef;
				return CString();
			}
		}
		void release()
		{
			if (--memoryRef == 0)
			{
				delete this;
			}
		}
		inline static void* operator new(unsigned int, unsigned int);
		inline static void* operator delete(void*);
		inline static ReferenceCounter* create(unsigned int);
		CHARTYPE* DeepCopy();
		inline void CopyString(unsigned int, const CHARTYPE*, unsigned int);
		inline void move(unsigned int, const CHARTYPE*, unsigned int);
		inline void set(unsigned int, const CHARTYPE*, unsigned int);
		inline bool excess_slop(unsigned int, unsigned int);
		inline long frob_size (unsigned int);
	private: 
		ReferenceCounter &operator= (const ReferenceCounter &);
    
	};
    
private:
    ReferenceCounter *refCounter() const
    {
        return reinterpret_cast<ReferenceCounter *>(value) - 1;
    }
    
    void RefUpdate(ReferenceCounter *pRef)
    {
        refCounter()->release();
        value = pRef->CString();
    }
    
public:
    const CHARTYPE* CString() const
    {
        return refCounter()->CString();
    }
    
    unsigned int Length() const
    {
        return refCounter()->memoryLength;
    }
    
    unsigned int Capacity() const
    {
        return refCounter()->Capacity;
    }
    
    unsigned int MaxSize() const
    {
        return (static_cast<unsigned int>(-1) - 1)/sizeof(CHARTYPE);
    }
    
    bool Empty() const
    {
        return Length() == 0;
    }
    
private:
    CHARTYPE * value;
};

template<class CHARTYPE, int MODETYPE, class ALLOCATOR>
inline BaseString<CHARTYPE, 0, MemoryConfigure<CHARTYPE> >::ReferenceCounter* BaseString<CHARTYPE, 0, MemoryConfigure<CHARTYPE> >::ReferenceCounter::
	operator new(long counterSize, long charTypeSize)
{
	return MemoryConfigure::allocate(counterSize + charTypeSize * sizeof(CHARTYPE));
}

template<class CHARTYPE, int MODETYPE, class ALLOCATOR>
inline void BaseString<CHARTYPE, 0, MemoryConfigure<CHARTYPE> >::ReferenceCounter::
	operator delete(void * ptr)
{
	MemoryConfigure::deallocate(ptr, sizeof(ReferenceCounter) + reinterpret_cast<ReferenceCounter *>(ptr)->memoryCapacity * 
		sizeof (CHARTYPE));
}

typedef BaseString <char> PJCOWString;
typedef BaseString <wchar_t> PJCOWWString;

#endif /* defined(__PJlib__PJString__) */
